
#ifndef SEMANTICS_METHOD_H

#define SEMANTICS_METHOD_H
#include "semantics_expression.h"
#include "stdio.h"
#include "generic_table.h"
#include "syntax_tree.h"
#include "semantics_field.h"
#include "semantics_enum.h"
//#include "semantics_property.h"

enum SemanticsMethodStatementType
{
	MetStatAssignment,
	MetStatMethodCall,
	MetStatIf,
	MetStatWhile,
	MetStatFor,
	MetStatDoWhile,
	MetStatSwitchCase,
	MetStatBreak,
	MetStatContinue,
	MetStatGoto,
	MetStatReturn,
	MetStatStart,
	MetStatStop,
	MetStatDerivationAssignment

};

class SemanticsMethodStatement
{
public:
	SemanticsMethodStatement()
	{

	}
	virtual ~SemanticsMethodStatement()
	{
	}

#ifdef DEBUG
	void DebugXMLOutput(FILE * fo);
#endif

	int Label; 
	SemanticsMethodStatementType Type;

	// type of statement

	// variable declaration is transformed to assignment...


};

class SemanticsMethodBody
{
public:
	SemanticsMethodBody();

	~SemanticsMethodBody();

#ifdef DEBUG
	void DebugXMLOutput(FILE * fo);
#endif


	GenericTable<SemanticsField> * LocalVariables;

	GenericTable<SemanticsMethodStatement> * Body;

};


// OTHER METHOD STATEMENTS THAT CONTAIN BODY
class SemanticsMethodStatementAssignment : SemanticsMethodStatement
{
public:
	SemanticsMethodStatementAssignment():SemanticsMethodStatement()
	{
		IsDeclaration = false;
		DataTypeName = new GenericTable<int>();
		LValue = NULL;
		RValue = NULL;
	}

	~SemanticsMethodStatementAssignment()
	{

	}

#ifdef DEBUG
	void DebugXMLOutput(FILE * fo);
#endif

	bool IsDeclaration;
	GenericTable<int> * DataTypeName;

	GenericTable<int> * LValue;
	SemanticsExpression * RValue;
};


class SemanticsMethodStatementMethodCall : public SemanticsMethodStatement
{
public:
	SemanticsMethodStatementMethodCall():SemanticsMethodStatement()
	{
		Name = new GenericTable<int>();
		Arguments = new GenericTable<SemanticsExpression>();
	}

	~SemanticsMethodStatementMethodCall()
	{

	}

#ifdef DEBUG
	void DebugXMLOutput(FILE * fo);
#endif

	GenericTable<int> * Name;
	// method name
	GenericTable<SemanticsExpression> * Arguments;
};


class SemanticsMethodStatementIf : SemanticsMethodStatement
{
public:
	SemanticsMethodStatementIf():SemanticsMethodStatement()
	{
		Expression = new SemanticsExpression();
		BodyIf = new SemanticsMethodBody();
		BodyElse = new SemanticsMethodBody();

	}

	~SemanticsMethodStatementIf()
	{

	}

#ifdef DEBUG
	void DebugXMLOutput(FILE * fo);
#endif

	SemanticsExpression * Expression;
	SemanticsMethodBody * BodyIf;
	SemanticsMethodBody * BodyElse;
};


class SemanticsMethodStatementWhile : SemanticsMethodStatement
{
public:
	SemanticsMethodStatementWhile():SemanticsMethodStatement()
	{
		Expression = new SemanticsExpression();
		LoopBody = new SemanticsMethodBody();

	}

	~SemanticsMethodStatementWhile()
	{
	}

#ifdef DEBUG
	void DebugXMLOutput(FILE * fo);
#endif

	SemanticsExpression * Expression;
	SemanticsMethodBody * LoopBody;
};


class SemanticsMethodStatementFor : SemanticsMethodStatement
{
public:
	SemanticsMethodStatementFor():SemanticsMethodStatement()
	{
		InitializationStatement = new SemanticsMethodStatement();
		Expression = new SemanticsExpression();
		RepeatStatement = new SemanticsMethodStatement();
		LoopBody = new SemanticsMethodBody();

	}

	~SemanticsMethodStatementFor()
	{
	}

#ifdef DEBUG
	void DebugXMLOutput(FILE * fo);
#endif

	SemanticsMethodStatement * InitializationStatement;
	SemanticsExpression * Expression;
	SemanticsMethodStatement * RepeatStatement;
	SemanticsMethodBody * LoopBody;
};



class SemanticsMethodStatementDoWhile : SemanticsMethodStatement
{
public:
	SemanticsMethodStatementDoWhile():SemanticsMethodStatement()
	{
		Expression = new SemanticsExpression();
		LoopBody = new SemanticsMethodBody();

	}

	~SemanticsMethodStatementDoWhile()
	{
	}

#ifdef DEBUG
	void DebugXMLOutput(FILE * fo);
#endif

	SemanticsMethodBody * LoopBody;
	SemanticsExpression * Expression;
};


class SemanticsMethodStatementCase : SemanticsMethodStatement
{
public:
	SemanticsMethodStatementCase():SemanticsMethodStatement()
	{
		Expression = NULL;
		CaseBody = NULL;
	}

	~SemanticsMethodStatementCase()
	{
	}

#ifdef DEBUG
	void DebugXMLOutput(FILE * fo);
#endif

	SemanticsExpression * Expression;
	SemanticsMethodBody * CaseBody;
};



class SemanticsMethodStatementSwitchCase : SemanticsMethodStatement
{
public:
	SemanticsMethodStatementSwitchCase():SemanticsMethodStatement()
	{
		Cases = new GenericTable<SemanticsMethodStatementCase>();
		LoopBody = NULL;
		Expression = NULL;
	}

	~SemanticsMethodStatementSwitchCase()
	{
	}

#ifdef DEBUG
	void DebugXMLOutput(FILE * fo);
#endif

	GenericTable<SemanticsMethodStatementCase> * Cases;
	SemanticsMethodBody * LoopBody;
	SemanticsExpression * Expression;
};



class SemanticsMethodStatementBreak : SemanticsMethodStatement
{
public:
	SemanticsMethodStatementBreak():SemanticsMethodStatement()
	{
	}

	~SemanticsMethodStatementBreak()
	{

	}

#ifdef DEBUG
	void DebugXMLOutput(FILE * fo);
#endif
};

class SemanticsMethodStatementContinue : SemanticsMethodStatement
{
public:
	SemanticsMethodStatementContinue():SemanticsMethodStatement()
	{
	}

	~SemanticsMethodStatementContinue()
	{

	}

#ifdef DEBUG
	void DebugXMLOutput(FILE * fo);
#endif
};


class SemanticsMethodStatementGoto : SemanticsMethodStatement
{
public:
	SemanticsMethodStatementGoto():SemanticsMethodStatement()
	{
		Name = new GenericTable<int>();
	}

	~SemanticsMethodStatementGoto()
	{
	}

#ifdef DEBUG
	void DebugXMLOutput(FILE * fo);
#endif

	GenericTable<int> * Name;
};


class SemanticsMethodStatementReturn : SemanticsMethodStatement
{
public:
	SemanticsMethodStatementReturn():SemanticsMethodStatement()
	{
		Expression = NULL;
	}

	~SemanticsMethodStatementReturn()
	{
	}

#ifdef DEBUG
	void DebugXMLOutput(FILE * fo);
#endif

	SemanticsExpression * Expression;
};


class SemanticsMethodStartAssignment
{
public:
	SemanticsMethodStartAssignment()
	{
		Name = new GenericTable<int>();
		Expression = NULL;
	}

	~SemanticsMethodStartAssignment()
	{
	}

#ifdef DEBUG
	void DebugXMLOutput(FILE * fo);
#endif

	GenericTable<int> * Name;
	SemanticsExpression * Expression; 

};

class SemanticsMethodStatementStart : SemanticsMethodStatement
{
public:
	SemanticsMethodStatementStart():SemanticsMethodStatement()
	{
		Name = new GenericTable<int>();
		Parameters = new GenericTable<SemanticsExpression>();
		WithAssignments = new GenericTable<SemanticsMethodStartAssignment>();
		HasWithPart = false;
	}

	~SemanticsMethodStatementStart()
	{
	}

#ifdef DEBUG
	void DebugXMLOutput(FILE * fo);
#endif

	GenericTable<int> *Name;
	GenericTable<SemanticsExpression> * Parameters;
	bool HasWithPart;
	GenericTable<SemanticsMethodStartAssignment> * WithAssignments;
};



class SemanticsMethodStatementStop : SemanticsMethodStatement
{
public:
	SemanticsMethodStatementStop():SemanticsMethodStatement()
	{
		Name = new GenericTable<int>();
	}

	~SemanticsMethodStatementStop()
	{
	}

#ifdef DEBUG
	void DebugXMLOutput(FILE * fo);
#endif

	GenericTable<int> *Name;
};



class SemanticsMethodStatementDerivationAssignment : SemanticsMethodStatement
{
public:
	SemanticsMethodStatementDerivationAssignment():SemanticsMethodStatement()
	{
		LValue = new GenericTable<int>();
		RValue = NULL;
	}

	~SemanticsMethodStatementDerivationAssignment()
	{
	}

#ifdef DEBUG
	void DebugXMLOutput(FILE * fo);
#endif

	GenericTable <int> * LValue;
	SemanticsExpression * RValue;
};



// OTHER CLASSES
class SemanticsMethodParameter
{
public:

	SemanticsMethodParameter();
	~SemanticsMethodParameter();

#ifdef DEBUG
	void DebugXMLOutput(FILE * fo);
#endif

	bool ModifierConst;

	SemanticsDataType * DataType;
	GenericTable<int> * Name;

};

class SemanticsMethodValuePair
{
public:
	SemanticsMethodValuePair()
	{
		this->minusParameterSign = false;
		this->minusValueSign = false;
	}

	~SemanticsMethodValuePair()
	{
	}

#ifdef DEBUG
	void DebugXMLOutput(FILE * fo);
#endif

	//promjena sintakse
	//bool IsINF;
	//bool INFSignMinus;

	bool minusParameterSign;
	bool minusValueSign;

	int Parameter;
	int Value;
};



class SemanticsMethod
{
public:
	SemanticsMethod();
	~SemanticsMethod();

	int parentContext;

	bool ModifierPrivate;
	bool ModifierPublic;
	bool ModifierProtected;
	bool ModifierStatic;
	bool ModifierAbstract;
	bool ModifierFinal;
	bool ModifierVirtual;
	bool ModifierOverride;


	bool IsConstructor;
	bool IsReadProperty;
	bool IsWriteProperty;

	bool IsNumeric;
	bool IsDiscrete;
	bool IsContinuous;

	bool HasMinusINF;
	bool HasPlusINF;

#ifdef DEBUG
	void DebugXMLOutput(FILE * fo);
#endif

	SemanticsDataType * DataType;
	GenericTable<int> * Name;

	SemanticsMethodStatementMethodCall * ConstructorInherit;
	GenericTable<SemanticsMethodValuePair> * ValuePairs;

	GenericTable<SemanticsMethodParameter> * Parameters;
	SemanticsMethodBody * MethodBody;

};

#endif
